/**
 * 之前的then方法无法进行链式调用，
 * 分析： then方法应该返回一个新的Promise
 * 上一个promise中then中的resolve和reject的返回值，将会成为新的promise中的resolve值
 * 上一个promise中只有执行了throw操作，才会进到下一个promise的reject回调中
 */

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(fn, value, resolve, reject) {
  try {
    const res = fn(value)
    resolve(res)
  } catch (err) {
    reject(err)
  }
}

class DDPromise {
  constructor(callback) {
    this.promiseStatus = PROMISE_STATUS_PENDING
    this.onFulfilledArr = []
    this.onRejectedArr = []
    const resolve = (value) => {
      if (this.promiseStatus === PROMISE_STATUS_PENDING) {
        console.log('resolve run, enter fulfilled status')
        //添加微任务
        queueMicrotask(() => {
          if (this.promiseStatus !== PROMISE_STATUS_PENDING) return
          this.promiseStatus = PROMISE_STATUS_FULFILLED
          this.value = value
          this.onFulfilledArr.forEach((onfulfilled) => {
            onfulfilled(this.value)
          })
        })
      }
    }
    const reject = (reason) => {
      if (this.promiseStatus === PROMISE_STATUS_PENDING) {
        console.log('reject run, enter rejected status')
        //添加微任务
        queueMicrotask(() => {
          if (this.promiseStatus !== PROMISE_STATUS_PENDING) return
          this.promiseStatus = PROMISE_STATUS_REJECTED
          this.reason = reason
          this.onRejectedArr.forEach((onreject) => {
            onreject(this.reason)
          })
        })
      }
    }
    try {
      callback(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  static resolve(value) {
    return new DDPromise((resolve, reject) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new DDPromise((resolve, reject) => {
      reject(reason)
    })
  }

  then(onFulfilled, onRejected) {
    onFulfilled =
      onFulfilled ||
      ((value) => {
        return value
      })
    onRejected =
      onRejected ||
      ((err) => {
        throw err
      })
    return new DDPromise((resolve, reject) => {
      if (this.promiseStatus === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.promiseStatus === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      if (this.promiseStatus === PROMISE_STATUS_PENDING) {
        //将成功回调和失败回调放到数组中
        this.onFulfilledArr.push(() => {
          if (onFulfilled)
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        })
        this.onRejectedArr.push(() => {
          if (onRejected)
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        })
      }
    })
  }

  catch(onRejected) {
    return this.then(undefined, onRejected)
  }

  finally(onFinally) {
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }
}

const promise = new DDPromise((resolve, reject) => {
  console.log('DDPromise run')
  // throw new Error('12343445')
  resolve('resolve msg...')
  // reject('reject msg...')
})
promise
  .then((res1) => {
    console.log('res1: ' + res1)
  })
  .catch((err) => {
    console.log(err)
  })
  .finally(() => {
    console.log('finally')
  })
